import type { AjaxInstance, AjaxInvoke, AjaxRequestConfig, AjaxResponse } from "uni-ajax";
import ajax from "uni-ajax";
import { BASE_URL } from "@/config";
import { useUserStore } from "@/stores/modules/user";
import { checkStatus } from "@/utils";

const _config: AjaxInstance<AjaxRequestConfig> = ajax.create({
  baseURL: BASE_URL,
  timeout: 60000
});

class RequestHttp {
  #requestInstance: AjaxInstance<AjaxRequestConfig>;
  constructor(_config: AjaxInstance<AjaxRequestConfig>) {
    this.#requestInstance = _config;

    this.#requestInstance.interceptors.request.use(
      (config: AjaxRequestConfig) => {
        const userStore = useUserStore();
        // request.header["Authorization"] = `Bearer ${userStore.initialState.token}`;
        config.header["Authori-Zation"] = `Bearer ${userStore.initialState.token}`;
        return config;
      },
      (error) => Promise.reject(error)
    );

    this.#requestInstance.interceptors.response.use(
      (response: AjaxResponse) => {
        const code = Number.parseInt(response.data.code || response.data.status) || 200;
        const msg = response.data.msg || response.data.message;
        if (code === 401 || code === 403) {
          uni.showToast({ title: msg, icon: "none" }).catch(() => {});
          return Promise.reject(msg);
        }
        if (code > 200 || code < 200) {
          uni.showToast({ title: msg, icon: "none" }).catch(() => {});
          return Promise.reject(msg);
        }
        return response.data;
      },
      (error) => {
        const { data, errMsg } = error;
        // 请求超时 && 网络错误单独判断，没有 response
        if (errMsg && errMsg.includes("request:fail")) uni.showToast({ title: "网络错误！请您稍后重试", icon: "none" }).catch(() => {});
        if (errMsg && errMsg.includes("timeout")) uni.showToast({ title: "请求超时！请您稍后重试", icon: "none" }).catch(() => {});
        // 根据服务器响应的错误状态码，做不同的处理
        if (data) checkStatus(data.status);
        return Promise.reject(error);
      }
    );
  }

  get<T = AjaxInvoke>(url: RequestType.AxiosConfig["url"], params: RequestType.AxiosConfig["params"] = {}, config: AjaxRequestConfig = {}): Promise<T> {
    return this.#requestInstance.get(url, params, config);
  }

  delete<T = AjaxInvoke>(url: RequestType.AxiosConfig["url"], params: RequestType.AxiosConfig["params"] = {}, config: AjaxRequestConfig = {}): Promise<T> {
    return this.#requestInstance.delete(url, params, config);
  }

  post<T = AjaxInvoke>(url: RequestType.AxiosConfig["url"], data: RequestType.AxiosConfig["data"] = {}, config: AjaxRequestConfig = {}): Promise<T> {
    return this.#requestInstance.post(url, data, config);
  }

  put<T = AjaxInvoke>(url: RequestType.AxiosConfig["url"], data: RequestType.AxiosConfig["data"] = {}, config: AjaxRequestConfig = {}): Promise<T> {
    return this.#requestInstance.put(url, data, config);
  }
}

export const Request = new RequestHttp(_config);
